package com.jy.modules.cims.settle.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.CimsConstant;
import com.jy.modules.cims.common.JResult;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.common.sysUtils.DateTimeUtils;
import com.jy.modules.cims.common.sysUtils.SearchParamUtil;
import com.jy.modules.cims.common.sysUtils.SimpleStringUtils;
import com.jy.modules.cims.common.sysUtils.SpringContextUtils;
import com.jy.modules.cims.component.common.service.TCMmCooperorgDealService;
import com.jy.modules.cims.component.common.service.TCMmTaskLogService;
import com.jy.modules.cims.component.credit.creditor.common.SettlePlan;
import com.jy.modules.cims.component.sysAssist.BatchService;
import com.jy.modules.cims.component.sysAssist.TaskLogImpl;
import com.jy.modules.cims.creditright.service.PlanService;
import com.jy.modules.cims.creditright.service.SettleAndSecondBuyService;
import com.jy.modules.cims.creditright.service.SettleCreditService;
import com.jy.modules.cims.data.common.dao.TCMmCostPlanDao;
import com.jy.modules.cims.data.common.dao.TCMmCreditSettleParamDao;
import com.jy.modules.cims.data.common.dao.TCMmRefundPlanDao;
import com.jy.modules.cims.data.common.dto.TCMmCooperorgDealDTO;
import com.jy.modules.cims.data.common.dto.TCMmCostPlanDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditSettleParamDTO;
import com.jy.modules.cims.data.common.dto.TCMmRefundPlanDTO;
import com.jy.modules.cims.data.common.dto.TCMmTaskLogDTO;
import com.jy.modules.cims.data.dao.CostPlanDao;
import com.jy.modules.cims.data.dao.CreditRightDao;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.CreditDetailQueryDto;
import com.jy.modules.cims.data.dto.CreditPackageDto;
import com.jy.modules.cims.data.dto.DealDto;
import com.jy.modules.cims.data.dto.credit.CreditSettleParam;
import com.jy.modules.cims.data.interact.core.credit.request.Request4029DTO;
import com.jy.modules.cims.data.interact.core.credit.request.RequestCreditListDTO;
import com.jy.modules.cims.data.interact.core.credit.request.RequestCustomInfoListDTO;
import com.jy.modules.cims.data.interact.core.credit.request.RequestPayBackListDTO;
import com.jy.modules.cims.deal.service.DealService;
import com.jy.modules.cims.interact.ICInteract;
import com.jy.modules.cims.sysassist.SysAssistService;

/**
 * 结算处理服务层
 */
@Service("com.jy.modules.cims.settle.service.SettleService")
public class SettleService {
	private static final Logger logger = LoggerFactory.getLogger(SettleService.class);
	// 核心受让接口处理状态
	private static String EXECUTEFINISH_TRUE = "1";// 核心受让接口处理状态（处理完成）
	private static String EXECUTEFINISH_FALSE = "0";// 核心受让接口处理状态（处理之中）
	private static final int DEFAULT_BATCH_COUNT = 100;// 每一次执行的条数
	private static final int DEFAULT_PAGE_SIZE = 2000;// 默认分页条数

	@Autowired
	private TCMmCostPlanDao tcmmCostPlanDao;

	@Autowired
	private TCMmRefundPlanDao tcmmfundPlanDao;

	@Autowired
	private TCMmCreditSettleParamDao tcmmCreditSettleParamDao;

	@Autowired
	private CreditRightDao creditRightDao;

	@Autowired
	private CostPlanDao costPlanDao;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.component.credit.creditor.common.SettlePlan")
	private SettlePlan settlePlan;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CCInteractImpl")
	public ICInteract iCInteract;

	@Autowired
	@Qualifier("com.jy.modules.cims.component.common.service.TCMmCooperorgDealService")
	private TCMmCooperorgDealService cooperorgDealService;

	@Autowired
	@Qualifier("com.jy.modules.cims.deal.service.DealService")
	public DealService dealService;

	@Autowired
	@Qualifier("com.jy.modules.cims.sysassist.SysAssistService")
	private SysAssistService sysAssistService;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.creditright.service.PlanService")
	private PlanService planService;

	@Autowired
	private SpringContextUtils springContextUtils;
	
	@Autowired
	@Qualifier("com.jy.modules.cims.component.sysAssist.BatchService")
	public BatchService batchService;

	/**
	 * @description 根据债权明细生成结算计划
	 * @author shengzhoutao
	 * @date 2015-07-21
	 * @param creditDeal
	 *            单条债权明细
	 * @throws Exception
	 */
	public void doCreateSettlePlan(final CreditDetailDto creditDeal) throws Exception {
		// 根据债权转让编号和债权编号查询是否有结算计划
		TCMmCostPlanDTO tcmmCostPlanDTO = new TCMmCostPlanDTO();
		tcmmCostPlanDTO.setTransferId(creditDeal.getTransferId());
		tcmmCostPlanDTO.setCreditorCode(creditDeal.getCreditCode());
		List<TCMmCostPlanDTO> tcmmCostPlanDTOList = tcmmCostPlanDao.searchTCMmCostPlan(SearchParamUtil.getSearchParam(tcmmCostPlanDTO));
		tcmmCostPlanDTO = null;
		// 如果存在结算计划，不需要生成新的结算计划
		if (CollectionsUtils.isNotEmpty(tcmmCostPlanDTOList)) {
			return;
		}
		// 只有信用贷才能生成结算计划，非信用贷，或者产品类型为空均不能生成结算计划
		String productType = creditDeal.getProductType();
		if (!SimpleStringUtils.hasText(productType)) {
			logger.info("产品类型：productType 为空！不能生成结算计划！");
			return;
		}
		if (SimpleStringUtils.hasText(productType) && (!CimsConstant.PRODUCT_TYPE_CREDIT.equals(productType))) {
			logger.info("产品类型为：{},非信用贷所以不能生成结算计划！", productType);
			return;
		}
		TCMmCreditSettleParamDTO creditSettleParamDTO = new TCMmCreditSettleParamDTO();
		creditSettleParamDTO.setContractCode(creditDeal.getContractCode());
		List<TCMmCreditSettleParamDTO> creditSettleParamDTOList = tcmmCreditSettleParamDao.searchTCMmCreditSettleParam(SearchParamUtil
				.getSearchParam(creditSettleParamDTO));
		creditSettleParamDTO = null;
		if (CollectionsUtils.isEmpty(creditSettleParamDTOList)) {
			logger.info(MessageFormat.format("根据合约编号[{0}]没有查询到债权结算参数记录！", new Object[] { creditDeal.getContractCode() }));
			return;
		}

		String settleType = creditSettleParamDTOList.get(0).getSettleType();
		if (!SimpleStringUtils.hasText(settleType)) {
			logger.info(MessageFormat.format("合约编号[{0}]结算计算方式(01:借款人结算方式;02:等额本息;03:按月付息)没有配置！", new Object[] { creditDeal.getContractCode() }));
			return;
		}
		String replaceType = creditSettleParamDTOList.get(0).getReplaceType();
		if (!SimpleStringUtils.hasText(replaceType)) {
			logger.info(MessageFormat.format("合约编号[{0}]月还处理方式(01:全额匹配;02:本金匹配;03:全额返还)没有配置！", new Object[] { creditDeal.getContractCode() }));
			return;
		}
		// 设置实体值
		CreditSettleParam creditSettleParam = new CreditSettleParam();
		creditSettleParam.setCreditCode(creditDeal.getCreditCode());// 债权编号
		creditSettleParam.setTransferId(creditDeal.getTransferId());// 转让编号
		creditSettleParam.setContractAmt(creditDeal.getContractSum());// 合同金额
		creditSettleParam.setRate(creditDeal.getMonthlyRate());// 月利率
		creditSettleParam.setTerm(creditDeal.getRepayPeriod().intValue());// 总期数
		creditSettleParam.setSurplusTerm(creditDeal.getResidueRepayPeriod().intValue());// 剩余期数
		creditSettleParam.setBillDate(creditDeal.getBillDate().toString());// 账单日
		creditSettleParam.setRepayType(settleType);// 结算计划规则
		creditSettleParam.setRepayStartDate(creditDeal.getRepayStartDate());// 起始还款日期
		creditSettleParam.setPromptyDate(creditDeal.getDeliverDate()); // 交割日
		creditSettleParam.setmReplaceType(replaceType);// 月还处理方式
		creditSettleParam.setFlag("1");

		// 调用方法生成结算计划
		settlePlan.initSettlePlan(creditSettleParam);

		creditSettleParam = null;
	}

	/**
	 * @description 发送结算计划
	 * @author shengzhoutao
	 * @date 2015-07-21
	 * @param creditDealList
	 * @param paramterMap
	 */
	public void sendApplyResultToConsult(List<CreditDetailDto> creditDealList, Map<Object, Object> paramterMap) {
		if (CollectionsUtils.isEmpty(creditDealList) || null == paramterMap) {
			logger.info("发送结算计划参数传递有问题。");
			return;
		}

		String dealCode = paramterMap.get("dealCode").toString();// 债权受让流水号
		String cooperorgCode = paramterMap.get("cooperorgCode").toString();// 债权受让流水号
		String executeFinish = paramterMap.get("lastBatch") == null ? "0" : paramterMap.get("lastBatch").toString();
		logger.info("executeFinish::" + executeFinish);

		if (!SimpleStringUtils.hasText(dealCode) || !SimpleStringUtils.hasText(cooperorgCode)) {
			logger.info("发送结算计划参数传递有问题。");
			return;
		}

		Request4029DTO request = new Request4029DTO();
		TCMmRefundPlanDTO tcmmRefundPlanDTO = null;
		RequestPayBackListDTO requestPayBackListDTO = null;
		RequestCustomInfoListDTO requestCustomInfoListDTO = null;
		List<RequestPayBackListDTO> paybackList = null;
		List<RequestCustomInfoListDTO> custominfoList = null;
		RequestCreditListDTO requestCreditListDTO = null;

		List<RequestCreditListDTO> creditList = new ArrayList<RequestCreditListDTO>();
		for (CreditDetailDto creditDetailDto : creditDealList) {
			// 查询还款计划
			tcmmRefundPlanDTO = new TCMmRefundPlanDTO();
			tcmmRefundPlanDTO.setTransferId(creditDetailDto.getTransferId());
			tcmmRefundPlanDTO.setCreditorCode(creditDetailDto.getCreditCode());
			List<TCMmRefundPlanDTO> tcmmRefundPlanDTOList = tcmmfundPlanDao.searchTCMmRefundPlan(SearchParamUtil.getSearchParam(tcmmRefundPlanDTO));
			// 如果没有还款计划重新再生产结算计划

			if (CollectionsUtils.isEmpty(tcmmRefundPlanDTOList)) {
				continue;
			}

			paybackList = new ArrayList<RequestPayBackListDTO>();
			custominfoList = new ArrayList<RequestCustomInfoListDTO>();
			for (TCMmRefundPlanDTO refundPlanDTO : tcmmRefundPlanDTOList) {
				// 填充还款计划数据
				requestPayBackListDTO = new RequestPayBackListDTO();
				requestPayBackListDTO.setContractNo(creditDetailDto.getContractCode());// 合同编号
				requestPayBackListDTO.setOtherCreditId(creditDetailDto.getCreditCode());// 债权编号
				requestPayBackListDTO.setTerm(refundPlanDTO.getCurrentTime().toString());// 期次号
				requestPayBackListDTO.setPayDate(refundPlanDTO.getStartDate());// 当期还款日
				requestPayBackListDTO.setMustBase(refundPlanDTO.getMustAmount());// 应还本金
				requestPayBackListDTO.setMustInst(refundPlanDTO.getMustAccrual());// 应还利息

				paybackList.add(requestPayBackListDTO);
			}

			// 填充客户信息数据
			requestCustomInfoListDTO = new RequestCustomInfoListDTO();
			requestCustomInfoListDTO.setCustCode(creditDetailDto.getCustCode());// 客户编号
			requestCustomInfoListDTO.setCustName(creditDetailDto.getCustName());// 客户名称
			requestCustomInfoListDTO.setCardId(creditDetailDto.getCardId());// 证件号码
			requestCustomInfoListDTO.setCardType(creditDetailDto.getCardType());// 证件类型
			custominfoList.add(requestCustomInfoListDTO);

			// 填充债权明细数据
			requestCreditListDTO = new RequestCreditListDTO();
			requestCreditListDTO.setContractNo(creditDetailDto.getContractCode());// 合同编号
			requestCreditListDTO.setOtherCreditId(creditDetailDto.getCreditCode());// 债权编号
			requestCreditListDTO.setBatchId(dealCode);// 批次号
			requestCreditListDTO.setContractValue(creditDetailDto.getContractSum());// 合同金额
			requestCreditListDTO.setLoanValue(creditDetailDto.getLoanSum());// 放款金额
			requestCreditListDTO.setLoanUserId(creditDetailDto.getCustCode());// 贷款人客户编号
			// requestCreditListDTO.setLoanUse("");// 贷款用途
			requestCreditListDTO.setInitialDate(creditDetailDto.getInitialLoanDate());// 初始放款日期

//			Date nextSettleDate = SettleDateImpl.getMinStartDate(tcmmRefundPlanDTOList);// 获取最小还款起始日
			requestCreditListDTO.setStartRepaymentDate(creditDetailDto.getRepayStartDate());// 还款起始日期
			requestCreditListDTO.setBillDate(creditDetailDto.getBillDate());// 账单日
			requestCreditListDTO.setRepaymentMonth(creditDetailDto.getRepayPeriod());// 还款期数
			requestCreditListDTO.setResidueRepayPeriod(creditDetailDto.getResidueRepayPeriod());// 剩余还款期数
			requestCreditListDTO.setEachRepaymentValue(tcmmRefundPlanDTOList.get(0).getThisRepaySum());// 每期还款金额
			requestCreditListDTO.setLoanProductName(creditDetailDto.getLoanProductName());// 贷款产品名称
			requestCreditListDTO.setLoanMonthlyInterest(creditDetailDto.getMonthlyRate());// 贷款产品月利率
			requestCreditListDTO.setRepaymentType(creditDetailDto.getRepayType());// 还款方式
			requestCreditListDTO.setMakeCreditorValue(creditDetailDto.getMakeCreditorValue());// 交割价值
			requestCreditListDTO.setDeliverDate(creditDetailDto.getDeliverDate());// 交割日期

			requestCreditListDTO.setCustominfoList(custominfoList);
			requestCreditListDTO.setPaybackList(paybackList);
			requestCreditListDTO.setLoanType(CimsConstant.mapProductType.get(creditDetailDto.getProductType()));

			creditList.add(requestCreditListDTO);
		}

		request.setCurrentBatchIsFull(executeFinish);// 本批次是否发送完毕(1：是；0：否)
		request.setcCode(cooperorgCode);// 合作机构编码
		request.setCreditList(creditList);// 受让债权
		// 调用接口发送结算计划
		iCInteract.sendSRCreditsToCore(request);

		// 修改交易流水状态
		try {
			DealDto dealDto = new DealDto();
			dealDto.setDealCode(dealCode);
			TCMmCooperorgDealDTO tCMmCooperorgDealDTO = cooperorgDealService.searchTCMmCooperorgDeal(SearchParamUtil.getSearchParam(dealDto)).get(0);
			if (EXECUTEFINISH_FALSE.equals(executeFinish)) {// 处理失败：接口状态还是-处理中
				tCMmCooperorgDealDTO.setInterfaceStatus(CimsConstant.INTERFACE_STATUS_RUN);
			} else if (EXECUTEFINISH_TRUE.equals(executeFinish)) {// 处理失败：接口状态还是-处理完成
				tCMmCooperorgDealDTO.setInterfaceStatus(CimsConstant.INTERFACE_STATUS_TRUE);
			}
			cooperorgDealService.updateTCMmCooperorgDeal(tCMmCooperorgDealDTO);
			dealDto = null;
		} catch (Exception e) {
			logger.error("修改交易流水号：" + dealCode + "的接口状态失败！", e);
		}
		tcmmRefundPlanDTO = null;
		requestPayBackListDTO = null;
		requestCustomInfoListDTO = null;
		paybackList = null;
		request = null;
	}

	/**
	 * @description 确认月还结算： 按照机构和债权来源分组分批月还现金结算
	 * @author shengzhoutao
	 * @param creditDetailDTO
	 *            查询条件
	 * @return JResult
	 * @throws Exception
	 */
	public JResult confirmSettle(CreditDetailDto queryDto) throws Exception {
		JResult result = new JResult();
		result.setSuccess(false);
		
		// 按照输入条件，查询所有符合结算交易，并且标志上需要结算的不同机构编号
		List<CreditDetailDto> creditDetailList = creditRightDao.searchSettleCooperorgCode(SearchParamUtil.getSearchParam(queryDto));
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			result.setErrMsg("没有符合结算条件的数据！");
			return result;
		}

		// SettleCreditService settleCreditService = springContextUtils.getBean(SettleCreditService.class);
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			queryDto.setCooperorgCode(creditDetailDto.getCooperorgCode());
			queryDto.setCreditSource(creditDetailDto.getCreditSource());
			
			// 按照输入条件，查询所有符合结算交易，并且标志上需要结算的债权明细的条数
			int totalCount = creditRightDao.getSettleCreditDetailRows(SearchParamUtil.getSearchParam(queryDto)).intValue();
			if (totalCount <= 0) {
				return result;
			}

			
			int pageSum = totalCount / DEFAULT_PAGE_SIZE;
			pageSum = (totalCount % DEFAULT_PAGE_SIZE == 0) ? pageSum : pageSum + 1;
			Map<String, Object> searchParams = null;
			for (int index = 1; index <= pageSum; index++) {
				searchParams = new HashMap<String, Object>();
				searchParams.put("dto", queryDto);
				searchParams.put("start", (index - 1) * DEFAULT_PAGE_SIZE + 1);
				searchParams.put("end", index * DEFAULT_PAGE_SIZE);

				// 按照输入条件，分页查询所有符合结算交易，并且标志上需要结算的债权明细
				creditDetailList = creditRightDao.searchSettleCreditDetail(searchParams);

				// 分批确认月还结算
				batchService.batchInvoke(SettleCreditService.class, "doConfirm", creditDetailList, null, DEFAULT_BATCH_COUNT);
				// settleCreditService.doConfirm(creditDetailList);
			}
		}
		
		result.setSuccess(true);
		return result;
	}
	
	/**
	 * @description 批量月还结算和二次购买匹配债权
	 * @author shengzhoutao
	 * @param creditPackageDto
	 *            债权包相关信息(定时任务按期结算需要传入结算日期：settleDate,该字段值是必须的。)
	 * @param taskFlag
	 *            是否定时任务处理标志(true:定时任务或批量处理;false:人工从页面单条触发处理)
	 * @return JResult 返回结果值
	 * @throws Exception
	 */
	public JResult batchSettleAndSecondBuy(final CreditPackageDto creditPackageDto, final Boolean taskFlag) throws Exception {		
		JResult result = new JResult();
		result.setSuccess(false);

		if (!SimpleStringUtils.hasText(creditPackageDto.getSettleDate())) {
			result.setErrMsg("按期结算需要传入结算日期：settleDate,该字段值是必须的。");
			return result;
		}

		// 校验核心日终状态
		String errMsg = sysAssistService.checkCoreStatus();
		if (SimpleStringUtils.hasText(errMsg)) {
			result.setErrMsg(errMsg);
			return result;
		}

		// 下面两个方法调用时间可能过长，所以放到定时任务触发执行。
		if (taskFlag) {
			repairSettltData(creditPackageDto);
		}

		// 获取所有需要处理的结算的债权包信息，定时任务执行需要处理历史未处理的数据
		List<CreditPackageDto> dealCreditPackageDtoList = getDealCreditPackageDtoList(creditPackageDto, taskFlag);
		if (CollectionsUtils.isEmpty(dealCreditPackageDtoList)) {
			errMsg = "没有符合结算的债权包信息";
			logger.info(errMsg);
			result.setErrMsg(errMsg);
			return result;
		}
		
		List<String> errMsgList = new ArrayList<String>();//定义处理的错误信息
		// 循环递归要处理的债权包信息
		for (CreditPackageDto dealCreditPackage : dealCreditPackageDtoList) {
			try {
				// 调用单条月还结算和二次购买匹配债权
				errMsg = settleAndSecondBuy(dealCreditPackage);
				if (SimpleStringUtils.hasText(errMsg)) {
					errMsgList.add(errMsg);
				}
			} catch (Exception e) {
				// 忽略错误，继续其它债权包处理
				logger.error("批量结算和二次购买:", e);
				errMsgList.add(e.getMessage());
			}
		}

		if (CollectionsUtils.isNotEmpty(errMsgList)) {
			errMsg = CollectionsUtils.convertToString(errMsgList, ";");
			result.setErrMsg(errMsg);
		} else {
			result.setSuccess(true);
		}

		return result;
	}

	/**
	 * @description repairSettltData 提前结算的结算计划要做变更;按照合约的结算参数重新计算结算计划返回金额和匹配金额.
	 * @param creditPackageDto
	 */
	public void repairSettltData(final CreditPackageDto creditPackageDto){
		// 忽略异常，继续执行
		try {
			// 终止结算计划全部已经结清，债权明细债权状态不正确数据
			creditRightDao.endCreditDetailForAllSettle(SearchParamUtil.getSearchParam(creditPackageDto));

			// 终止赎回两边系统状态不一致的历史债权明细
			creditRightDao.endCreditDetailForHistoryRedeem(SearchParamUtil.getSearchParam(creditPackageDto));
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		
		// 忽略异常，继续执行
		try {
			// 月还交易前先要生成和变更还款计划、计算计划：特别是提前结算的结算计划要做变更，防止提前结清数据当正常月还处理
			planService.buildPlan();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		
		// 忽略异常，继续执行
		try {
			// 终止当天转让确认对应结算计划表的结算状态
			costPlanDao.endCostPlanForCurrentConfirmCredit(SearchParamUtil.getSearchParam(creditPackageDto));
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
				
		// 忽略异常，继续执行
		// 如果合约的结算规则出现变更，需要重新按照合约的结算参数重新计算结算计划返回金额和匹配金额。
		try {
			CreditDetailQueryDto creditDetailDto = new CreditDetailQueryDto();
			creditDetailDto.setCooperorgCode(creditPackageDto.getCooperorgCode());
			creditDetailDto.setSettleDate(creditPackageDto.getSettleDate());
			planService.doUpdateCostPlanAmount(creditDetailDto);
			creditDetailDto = null;
		} catch (Exception e) {
			logger.error(e.getMessage());
		}	
	}
	
	/**
	 * @description 单条月还结算和二次购买匹配债权
	 * @author shengzhoutao
	 * @param creditPackage
	 *            债权包相关信息，以下信息为必须项：机构编号、合约编号、债权包、结算日期
	 * @return errMsg 错误信息
	 * @throws Exception
	 */
	public String settleAndSecondBuy(final CreditPackageDto creditPackage) throws Exception {
		String errMsg = null;

		String cooperorgCode = creditPackage.getCooperorgCode();
		String contractCode = creditPackage.getContractCode();
		String creditPackageName = creditPackage.getCreditPackageName();
		String settleDate = creditPackage.getSettleDate();

		List<CreditDetailQueryDto> creditDetailQueryDtoList = new ArrayList<CreditDetailQueryDto>();
		creditDetailQueryDtoList.add(getCreditPackageDto(cooperorgCode, contractCode, creditPackageName, settleDate));

		// 如果配置二次购买，根据合约配置关系找符合条件的结算包。////////
		if (SimpleStringUtils.hasText(creditPackage.getSecondCode())) {
			creditDetailQueryDtoList.add(getCreditPackageDto(cooperorgCode, creditPackage.getSecondCode(),
					creditPackageName + (creditPackage.getSecondPagSuffix() == null ? "" : creditPackage.getSecondPagSuffix().trim()), settleDate));
		} // ////////////////////////////////////////////

		SettleAndSecondBuyService settleAndSecondBuyService = springContextUtils.getBean(SettleAndSecondBuyService.class);
		// 再次查询，过滤不符合条件的结算数据。
		List<CreditDetailQueryDto> newCreditDetailQueryDtoList = settleAndSecondBuyService.filterCreditDetailQueryDtoList(creditDetailQueryDtoList);
		creditDetailQueryDtoList = null;

		// 根据条件查询月还结算的历史流水。
		List<DealDto> oldSettleDealDtoList = settleAndSecondBuyService.getCooperorgDealBySettle(cooperorgCode, contractCode, creditPackageName,
				settleDate);
		
		TaskLogImpl taskLogImpl = springContextUtils.getBean(TaskLogImpl.class);
		
		// 没有未结算的债权，并且也没有已经结算的历史流水，不需要处理。
		if (CollectionsUtils.isEmpty(newCreditDetailQueryDtoList) && CollectionsUtils.isEmpty(oldSettleDealDtoList)) {
			// 删除无用历史记录
			taskLogImpl.deleteTCMmTaskLog(cooperorgCode, contractCode, creditPackageName, settleDate);
			return errMsg;
		}

		// 按照条件查询日志		
		List<TCMmTaskLogDTO> tcmmTaskLogDTOList = taskLogImpl.searchTCMmTaskLog(cooperorgCode, contractCode, creditPackageName, settleDate);
		Long id = taskLogImpl.saveOrUpdateTCMmTaskLog(tcmmTaskLogDTOList, cooperorgCode, contractCode, creditPackageName, settleDate);
		if (null == id) {
			return errMsg;
		}

		// ///////////////////////////////////////////////
		String exeStatus = CimsConstant.EXE_STATUS_BEGIN; // 执行状态
		//String errorInfo = "";// 错误信息
		try {
			// 批量结算和二次购买
			DealDto secondBuyDealDto = settleAndSecondBuyService.doSettleAndSecondBuy(creditPackage, oldSettleDealDtoList, newCreditDetailQueryDtoList);

			// 确认债权购买(二次购买)结果，忽略异常
			settleAndSecondBuyService.confirmSecondBuy(secondBuyDealDto);
			exeStatus = CimsConstant.EXE_STATUS_END;
		} catch (Exception e) {
			exeStatus = CimsConstant.EXE_STATUS_ERROR;
			//errorInfo = ExceptionUtils.getStackTraceAsString(e);
			logger.error("月还结算和二次购买匹配债权异常：", e);
			errMsg = e.getMessage();
			errMsg = (null == errMsg ? "程序出错，赋值有空。" : errMsg);
		} finally {
			taskLogImpl.updateTCMmTaskLogExeStatus(id, exeStatus, errMsg);
			taskLogImpl.updateAmount(cooperorgCode, contractCode, creditPackageName, settleDate);
		}
		// ///////////////////////////////////////////////

		return errMsg;
	}

	/**
	 * @description 获取所有需要处理的结算的债权包信息
	 * @author shengzhoutao
	 * @param creditPackageDto
	 *            查询条件
	 * @param isDealUnfinished
	 *            是否处理历史未处理的数据
	 * @return dealCreditPackageDtoList 所有需要处理的结算的债权包信息
	 * @throws Exception
	 */
	private List<CreditPackageDto> getDealCreditPackageDtoList(CreditPackageDto creditPackageDto, Boolean isDealUnfinished) throws Exception {
		SettleAndSecondBuyService settleAndSecondBuyService = springContextUtils.getBean(SettleAndSecondBuyService.class);

		// 所有需要处理的结算的债权包信息
		List<CreditPackageDto> dealCreditPackageDtoList = new ArrayList<CreditPackageDto>();

		if (isDealUnfinished) {
			// 历史处理失败未完成的结算的债权包信息
			List<CreditPackageDto> unfinishedCreditPackageDtoList = getUnfinishedCreditPackageDto();
			if (CollectionsUtils.isNotEmpty(unfinishedCreditPackageDtoList)) {
				dealCreditPackageDtoList = CollectionsUtils.union(dealCreditPackageDtoList, unfinishedCreditPackageDtoList);
			}
		}

		// 查询出当前符合结算的债权包信息
		List<CreditPackageDto> currentCreditPackageDtoList = settleAndSecondBuyService.searchCreditPackageForSettle(creditPackageDto);
		if (CollectionsUtils.isNotEmpty(currentCreditPackageDtoList)) {
			List<CreditPackageDto> newCurrentCreditPackageDtoList = new ArrayList<CreditPackageDto>();
			for (CreditPackageDto temp : currentCreditPackageDtoList) {
				temp.setSettleDate(creditPackageDto.getSettleDate());
				newCurrentCreditPackageDtoList.add(temp);
			}
			dealCreditPackageDtoList = CollectionsUtils.union(dealCreditPackageDtoList, newCurrentCreditPackageDtoList);
			newCurrentCreditPackageDtoList = null;
		}

		return dealCreditPackageDtoList;
	}
	
	//
	private List<CreditPackageDto> getUnfinishedCreditPackageDto() throws Exception {
		List<CreditPackageDto> unfinishedCreditPackageDtoList = new ArrayList<CreditPackageDto>();

		// 根据日志记录查询史处理失败未完成的结算的债权包信息
		TCMmTaskLogService tcmmTaskLogService = springContextUtils.getBean(TCMmTaskLogService.class);
		TCMmTaskLogDTO queryTaskLogDto = new TCMmTaskLogDTO();
		queryTaskLogDto.setExeStatus(CimsConstant.EXE_STATUS_ERROR);
		List<TCMmTaskLogDTO> dataList = tcmmTaskLogService.searchTCMmTaskLog(SearchParamUtil.getSearchParam(queryTaskLogDto));
		queryTaskLogDto = null;
		
		if (CollectionsUtils.isEmpty(dataList)) {
			return unfinishedCreditPackageDtoList;
		}

		// 按照结算日期从小到到大排序
		try {
			Collections.sort(dataList, new Comparator<TCMmTaskLogDTO>() {
				public int compare(TCMmTaskLogDTO arg0, TCMmTaskLogDTO arg1) {
					return arg0.getSettleDate().compareTo(arg1.getSettleDate());
				}
			});
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

		CreditPackageDto unfinishedCreditPackageDto = null;
		for (TCMmTaskLogDTO logDTO : dataList) {
			unfinishedCreditPackageDto = new CreditPackageDto();
			unfinishedCreditPackageDto.setCooperorgCode(logDTO.getCooperorgCode());
			unfinishedCreditPackageDto.setContractCode(logDTO.getContractCode());
			unfinishedCreditPackageDto.setCreditPackageName(logDTO.getCreditPackageName());
			unfinishedCreditPackageDto.setSettleDate(DateTimeUtils.formatDate(logDTO.getSettleDate(), "yyyy-MM-dd"));

			unfinishedCreditPackageDtoList.add(unfinishedCreditPackageDto);
		}
		unfinishedCreditPackageDto = null;

		return unfinishedCreditPackageDtoList;
	}
	
	//
	private CreditDetailQueryDto getCreditPackageDto(final String cooperorgCode, final String contractCode, final String creditPackageName,
			final String settleDate) {
		CreditDetailQueryDto creditDetailQueryDto = new CreditDetailQueryDto();
		creditDetailQueryDto.setCooperorgCode(cooperorgCode);
		creditDetailQueryDto.setContractCode(contractCode);
		creditDetailQueryDto.setPackageNum(creditPackageName);
		creditDetailQueryDto.setSettleDate(settleDate);

		return creditDetailQueryDto;
	}
}